import { App } from '../../../../src/App';
import { CallScore, CreateLandlord, Deal, Discard, EntryRoom, GameModule, LandlordEvents, PlayerIdentity, Ready, Settlement } from '../Game/GameModule';
import PokerWall from '../../src/Component/PokerWall';
import GameLogic from '../Game/GameLogic';
import { PokerData, PokerType, Union } from '../../../src/BaseLogic';
import { UserData } from '../../../src/BaseModule';
import Map from '../../../../src/core/Map';

const {ccclass, property} = cc._decorator;

interface EffectCfg {
    path:string,          // 文件夹
    gotoAndPlay:string[], // 动画名
    armatureName:string,  // 动画名
    playTimes:number,     // 播放次数
    type:number,          // 牌型
};

@ccclass
export default class RoomScene extends cc.Component {
    @property(cc.Node)
    btnPass: cc.Node = null;
    @property(cc.Node)
    btnTips: cc.Node = null;
    @property(cc.Node)
    btnDiscard: cc.Node = null;
    @property(cc.Node)
    btnReady:cc.Node = null;
    @property(cc.Node)
    pnlGameOver:cc.Node = null;
    @property(cc.Label)
    lblRoomName:cc.Label = null;
    @property(cc.Label)
    lblBaseScore:cc.Label = null;
    @property(cc.Label)
    lblNoPoker:cc.Label = null;
    @property(cc.Label)
    lblWait:cc.Label = null;
    @property(cc.Label)
    lblStates:cc.Label[] = [];
    @property(cc.Label)
    lblTimes:cc.Label[] = [];
    @property(cc.Label)
    lblCounts:cc.Label[] = [];
    @property(cc.Node)
    imgLandlordFlag:cc.Node[] = [];
    @property(cc.Node)
    showPokes:cc.Node[] = [];
    
    @property({ type: cc.Node})
    moveNode: cc.Node = null;
    @property({ type: cc.Node})
    callLayout: cc.Node = null;
    @property({ type: cc.Node})
    handLayout: cc.Node = null;
    @property(cc.Node)
    cannotTips:cc.Node = null;
    @property(cc.Node)
    romeInfoNode:cc.Node = null;
    @property(cc.Node)
    obviousNode:cc.Node = null;

    @property(cc.Node)
    discardCtrlLayout:cc.Node = null;
    @property(cc.Node)
    touchLayout:cc.Node = null;
    @property(cc.Node)
    effectsLayout:cc.Node = null;

    private _hands:PokerData[] = [];
    private _canDiscard:Union[] = null;
    private _choseCards:Union = null;
    private _stateFlag:string[] =[];
    private _ghostNode: cc.Node[] = [];
    private _discardInfo:Map<number,PokerData[]> = new Map<number,PokerData[]>();
    private _landlord:number = -1;
    private _autoLeave:any = null;
    private _waitHand:any = null;
    private _selfSeat:number = -1;
    private _seatInfo:Map<number,UserData> = new Map<number,UserData>(); 
    private _effects:Map<string,EffectCfg> = new Map<string,EffectCfg>();
    
    private _roomCfg:{id:number,name:string,minScore:number} = null;

    onLoad(){
        this.lblWait.node.active = true;
        this.lblNoPoker.node.active = false;
        App.Util.playLabelDot(this.lblWait);
        this._clearTable();
        App.CSV.load('csv/effects:room',(cfg:any[])=>{
            cfg && cfg.forEach((it)=>{
                const tmp:EffectCfg = {
                    path:it.path,          // 文件夹
                    gotoAndPlay:it.gotoAndPlay, // 动画名
                    armatureName:it.armatureName,
                    playTimes:it.playTimes,     // 播放次数
                    type:it.type,          // 牌型
                };
                this._effects.inset(it.path,tmp);
            });
        });

        this.romeInfoNode.active = true;
        this.moveNode.active = false;
        const cfg = GameModule.roomData;
        this.lblBaseScore.string = App.Util.format(App.getText('landlord.base_score'),App.Util.formatScore(cfg.BetMin));
        this.lblRoomName.string = `${cfg.ConfName}`;
        this._roomCfg = cfg;
        this._landlord = -1;
        this.btnReady.active = true;

        this._stateFlag = App.getText('landlord.state_flag').split('|').slice(0);
        [0,1,2].forEach((idx)=>{this._resetSeat(idx)});

        App.justNode(this.pnlGameOver);

        const CallAudio:string[] = ['w_jiaofen_0','w_jiaofen_1','w_jiaofen_2','w_jiaofen_3'];
        const CallScore:string[]=App.getText('landlord.call_score0').split('|').slice(0);
        const discardBtn:cc.Node[] = [this.btnPass,this.btnTips,this.btnDiscard];
        const initX = this.showPokes[0].getComponent(cc.Layout).spacingX;
        let   curCallScore:number = -1;
        // -----------------------------------------------事件监听-----------------------------------------------
        App.Event.on(LandlordEvents.EC_UPDATE_USER_INFO,(data:UserData)=>{
            this._createSeat(0,data);
        },this);

        let readyCount = 0;
        App.Event.on(LandlordEvents.EC_ENTRY_ROOM,(data:EntryRoom)=>{
            console.log(`RoomScene.entry_room:${JSON.stringify(data)}`);
            this._createSeat(data.seat,data.user);
            ++readyCount;
            if (readyCount > 1){
                this.lblWait.node.active = false;
                App.Util.closeLabelDot(this.lblWait);
            }
        },this);

        App.Event.on(LandlordEvents.EC_READY,(data:Ready)=>{
            console.log(`RoomScene.ready:${JSON.stringify(data)}`);
            this._setState(this._stateFlag[0],data.seat);
        },this);
        
        App.Event.on(LandlordEvents.EC_DEAL,(data:Deal)=>{
            this._clearTable();
            data.info.forEach((it,idx)=>{
                this._setState('',idx);
                if (it.seat === this._selfSeat){
                    console.log(`RoomScene.deal:${this._selfSeat}=${JSON.stringify(data.info[this._selfSeat].cards)}`);
                    this._hands = it.cards;
                }
                const id = setTimeout((dt:any) => {
                    clearTimeout(id);
                    this._movePokerActive(cc.v2(0,0),dt.seat,(seat:number)=>{
                        GameModule.playEffect('fapai');
                        if (seat === this._selfSeat){
                            this.handLayout.getComponent(PokerWall).insert(dt.cards,true,true);
                        } else{
                            this._setHandsCount(seat,dt.cards.length);
                        } 
                        // 设置底牌
                        if (seat+1 === GameModule.MaxSeat){
                            const wall = this.showPokes[0].getComponent(PokerWall);
                            wall.setSpacing(0);
                            wall.insert(data.baseCards);
                            this.discardCtrlLayout.active = dt.seat === this._selfSeat;
                        }
                    });
                }, idx*2000,it);
            });
        },this);
        
        App.Event.on(LandlordEvents.EC_NOTICE_CALL,(data:CallScore)=>{
            if (data.next === this._selfSeat){
                for (let i = 1; i < this.callLayout.childrenCount; ++i){
                    this.callLayout.children[i].active = i > data.score;
                }
                this.callLayout.active = true;
            }
        },this);

        // 叫分
        App.Event.on(LandlordEvents.EC_CALL,(data:CallScore)=>{
            console.log(`RoomScene.call:${data.seat}=${JSON.stringify(data)}`);
            if (data.seat < 0 || data.seat > 3) return ;
            if (curCallScore > 0 && data.score > curCallScore){
                GameModule.playEffect('w_jiaodizhu_1');
                curCallScore = data.score;
            }
            setTimeout(() => {
                GameModule.playEffect(CallAudio[data.score]);
                this._setState(CallScore[data.score],data.seat,cc.color(49,146,113));
            }, 1000);
        },this);
        
        App.Event.on(LandlordEvents.EC_BUILD_BANKER,(data:CreateLandlord)=>{
            curCallScore = -1;
            console.log(`RoomScene.build_landlord:${JSON.stringify(data)}`);
            this._setState(CallScore[data.score],data.seat,cc.color(49,146,113));
            this.callLayout.active = false;
            this._landlord = data.seat;
            this.callLayout.active = false;
            const selfHand = this.handLayout.getComponent(PokerWall);
            selfHand.touch = true;
            const wall = this.showPokes[0].getComponent(PokerWall);
            const layout = this.showPokes[0].getComponent(cc.Layout);
            cc.tween(layout)
            .to(0.1,{spacingX:-1*wall.itemSize.width})
            .call(()=>{
                wall.remove();
                layout.spacingX = initX;
                this._movePokerActive(cc.v2(0,0),data.seat,()=>{
                    this.obviousNode.parent.opacity = 255;
                    this.romeInfoNode.active = false;
                    this.obviousNode.getComponent(PokerWall).insert(data.cards,false,true);
                    this._setHandsCount(data.seat,GameModule.MaxHands+data.cards.length);
                    this._setWaitTime(data.seat,GameModule.MaxWaitTime);
                    if (data.seat === this._selfSeat){
                        this._hands = App.Util.concatArray(this._hands,data.cards)
                        selfHand.insert(data.cards,true,true,true);
                        selfHand.showFlag(true);
                    }
                });
            })
            .delay(1)
            .call(()=>{
                this.imgLandlordFlag.forEach((img,idx)=>{
                    this._setState('',idx);
                    img.active = idx === data.seat;
                });

                if (this._landlord === this._selfSeat){
                    discardBtn[0].active = false;
                    discardBtn.forEach((btn,idx)=>{idx > 0 && (btn.active = true);});
                    this.discardCtrlLayout.active = true;
                }
            }).start();
        },this);

        // 出牌
        App.Event.on(LandlordEvents.EC_NOTICE_DISCARD, (data:Discard)=>{
            console.log(`RoomScene.notice_discard:${JSON.stringify(data)}`);
            this._clearTime(data.seat);
            this._setState('',data.seat);
            App.Audio.stopLoopEffect();
            if (data.seat === this._selfSeat && data.cards.length > 0){
                data.cards.forEach((card:PokerData)=>{
                    const index = this._hands.indexOf(card);
                    index > -1 && this._hands.splice(index,1);
                });
                this.handLayout.getComponent(PokerWall).remove(data.cards);
            } else {
                const count = parseInt(this.lblCounts[data.seat].string);
                this._setHandsCount(data.seat,count-data.cards.length);
            }

            // 当前玩家出牌，把桌面的出牌信息清空
            if (data.cards.length > 0){
                this.showPokes.forEach((it)=>{
                    it.getComponent(PokerWall).remove();
                });
            }

            this._discardInfo.inset(data.seat,data.cards);
            this._playEffect(data.cards,data.seat,()=>{
                if (data.cards.length > 0){
                    GameModule.playEffect('chupai');
                    const wall = this.showPokes[data.seat].getComponent(PokerWall);
                    wall.insert(data.cards,false,true);
                }
                
                if (data.next === this._selfSeat){
                    const last:Discard = GameModule.getLast(this._selfSeat,this._discardInfo);
                    this._canDiscard = GameLogic.findCanDiscard(this._hands,last.seat === this._selfSeat ? []:last.cards,true);
                    this.lblNoPoker.node.active = !this._canDiscard;
                    this.lblNoPoker.node.setPosition(this.handLayout.getPosition());
                    this._setWaitTime(this._selfSeat,this._canDiscard ? data.delayTime : 0);
                    if (!this._canDiscard){
                        discardBtn[0].active = true;
                        discardBtn.forEach((btn,idx)=>{
                            idx > 0 && (btn.active = false);
                        });
                        setTimeout(() => {
                            this.lblNoPoker.node.active = false;
                            this.onClickPass();
                        }, 2000);
                    } else {
                        discardBtn[0].active = last.seat !== this._selfSeat; // 必须出牌，上两家过牌了
                        discardBtn.forEach((btn,idx)=>{
                            idx > 0 && (btn.active = true);
                        });
                    }
                } else {
                    this.showPokes[data.next] && this.showPokes[data.next].getComponent(PokerWall).remove(); 
                    this._setState('',data.next);
                    this._setWaitTime(data.next,data.delayTime);
                }
                this.discardCtrlLayout.active = (data.next === this._selfSeat && App.Util.isValid(this._canDiscard));
            });
        },this);

        App.Event.on(LandlordEvents.EC_GAME_OVER, (data:Settlement)=>{
            console.log(`RoomScene.game_over:${JSON.stringify(data)}`);
            this._clearTable();
            const gameOver = ()=>{
                this._playAnimation(this._effects.find('shuying'),data.win === PlayerIdentity.landlord?0:1,()=>{
                    const isWin = data.info[0].score > 0;
                    data.info.forEach((it:any,idx:number)=>{
                        let user = this._seatInfo.find(it.seat);
                        if (user){
                            user.Coin += it.score;
                            const node = App.Util.find<cc.Node>(`gameLayout/play_0${it.seat}`,this.node);
                            App.Util.isValid(data) && App.Util.isValid(node) && App.setLableText(node,'head/lblCoin',App.Util.formatScore(user.Coin));
                        }
        
                        const item:cc.Node = App.Util.find<cc.Node>(`gameOver/item0${idx}`,this.pnlGameOver);
                        if (App.Util.isValid(item)){
                            App.setLableText(item,'lblName',it.name);
                            App.setLableText(item,'lblBaseScore',App.Util.formatScore(GameModule.roomData.BetMin));
                            App.setLableText(item,'lblTotalScore',App.Util.formatScore(it.score));
                            App.Util.find<cc.Node>(`lblName/imgLandlord`,item).active = it.flag === PlayerIdentity.landlord;
                            if (it.seat === idx){
                                App.Util.find<cc.Node>('gameOver/imgTitle',this.pnlGameOver).getComponent('MultiPlug').setValue(isWin?0:1);
                            }
                        }
            
                        idx >= (data.info.length-1) && this._setSettlement(true,()=>{
                            GameModule.playEffect(isWin?'shengli':'shibai');
                        });
                    });
                });
            };

            if (data.spring > -1){
                this._playAnimation(this._effects.find('spring'),data.win,()=>{gameOver()});
            } else gameOver();
        },this);


        this.touchLayout.on(cc.Node.EventType.TOUCH_START, this._onTouchStart, this);
    }

    start () {
        App.Audio.randomPlayDir(['music/bgm04:room','music/bgm05:room','music/bgm06:room','music/bgm07:room']);

        const top = App.Util.find<cc.Node>('topNode',this.node);
        const initY = top.y;
        top.y += (cc.view.getFrameSize().height+top.height);
        console.log(`topY=${top.y}`)
        cc.tween(top)
        .to(0.2,{y:initY-50},{easing:'quadIn'})
        .to(0.2,{y:initY},{easing:'elasticOut'})
        .call(()=>{
            this._createSeat(0,GameModule.userInfo);
            this._selfSeat = 0;
        }).start();
    }

    onDestroy(){
        this.touchLayout.off(cc.Node.EventType.TOUCH_START, this._onTouchStart, this);
        App.Event.offAll(this);
    }

    onClickReady(){
        this.btnReady.active = false;
        this._clearTable();
        App.Event.emit(LandlordEvents.EC_READY,{seat:0,next:-1});
        GameModule.playing=true;
    }

    onClickHead(_,idx){
        const index = parseInt(idx);
        if (index === 0){
            App.openView(`UserInfo:hall`);
            return ;
        }

        // 点击其他头像则是进行交互操作
        //const node = this.
    }

    onClickShare(){
        App.popTips(App.getText('developing'));
    }

    onClickSet(){
        App.openView('Set:hall');
    }

    onClickGoHall(){
        if (GameModule.isPlaying){
            App.popTips(App.getText('landlord.game_progress'));
            return ;
        }
        App.MessageBox(App.getText('landlord.back_hall'),(flag)=>{
            if (flag === App.MB_FLAG.OK){
                if (GameModule.isPlaying){
                    App.popTips(App.getText('landlord.game_progress'));
                    return ;
                }

                GameModule.exitRoom();
            } else {
                if (this._seatInfo.find(this._selfSeat).Coin < GameModule.roomData.BetMin){
                    App.MessageBox(App.getText('landlord.no_factor'),(flag:number)=>{
                        if (flag === App.MB_FLAG.OK){
                            App.Event.emit(LandlordEvents.EC_WATCH_VIDEO);
                        }
                    });
                    return ;
                }
                this.btnReady.active = true;
            }
        });
    }
    
    onClicketBack(){
        this._setSettlement(false,()=>{
            GameModule.exitRoom();
        });
    }

    onClicketContinue(){
        this._setSettlement(false,()=>{
            if (this._seatInfo.find(this._selfSeat).Coin < GameModule.roomData.BetMin){
                App.MessageBox(App.getText('landlord.no_factor'),(flag:number)=>{
                    if (flag === App.MB_FLAG.OK){
                        App.Event.emit(LandlordEvents.EC_WATCH_VIDEO);
                    }
                });
                return ;
            }
            GameModule.isSingle && (GameModule.userInfo.Coin -= GameModule.roomData.BetMin);
            App.setLocalStorage(GameModule.userInfo,App.LOCAL_KEY.USER);
            this.onClickReady();
            App.Event.emit(LandlordEvents.EC_GAME_RESSET);
        });
    }

    onClickChat(){
        App.popTips(App.getText('developing'));
    }

    onClickPass(){      
        const pkg:Discard = {
            cards:[], //打出的牌组信息
            seat:0,       // 谁出的
            next:1,       // 下家
            delayTime:-1,
        };
        App.Event.emit(LandlordEvents.EC_DISCARD,pkg);
        this._canDiscard = null;
        this._clearTime(this._selfSeat);
        this.discardCtrlLayout.active = false;
        const wall = this.handLayout.getComponent(PokerWall);
        wall.cancelSelect();
    }

    onClickTips(){
        if (!this._canDiscard){
            this._choseCards = null;
            const last = GameModule.getLast(this._selfSeat,this._discardInfo);
            this._canDiscard = GameLogic.findCanDiscard(this._hands,last.seat === this._selfSeat ? []:last.cards,true);
            if (!this._canDiscard || this._canDiscard.length < 1){
                App.popTips(App.getText('landlord.too_small'));
                return ;
            }
        }

        this._choseCards = this._canDiscard[0];
        const tmp = App.Util.getNextOrBack(this._canDiscard,this._choseCards);
        if (tmp && tmp.cards.length > 0){
            const wall = this.handLayout.getComponent(PokerWall);
            wall.cancelSelect();
            wall.autoSelect(tmp.cards);
            this._choseCards = tmp;
        }
    }

    onClickDiscard(){
        const handWall = this.handLayout.getComponent(PokerWall);
        const _select = handWall.selects.slice(0);
        if (_select.length < 1){
            App.popTips(App.getText('landlord.unselect_poker'));
            return ;
        }
        if (GameLogic.isValid(_select,GameModule.getLast(this._selfSeat,this._discardInfo).cards)){
            const pkg:Discard = {
                cards:_select, //打出的牌组信息
                seat:0,       // 谁出的
                next:1,       // 下家
                delayTime:-1,
            };
            App.Event.emit(LandlordEvents.EC_DISCARD,pkg);
            this._canDiscard = null;
            this.discardCtrlLayout.active = false;
            return ;
        }
        App.popTips(App.getText('landlord.too_small'));
    }

    onClickCall(_, customEventData){
        App.Event.emit(LandlordEvents.EC_CALL,{seat:0,score:parseInt(customEventData),next:1});
        this.callLayout.active = false;
    }

    onClickRules() {
        App.openView(`Rule:room`);
    }

    onClickVedio() {
        App.Event.emit(LandlordEvents.EC_WATCH_VIDEO);
    }

    private _onTouchStart(event: cc.Event.EventTouch) {
        this.handLayout.getComponent(PokerWall).cancelSelect();
    };

    public _createSeat(seat:number, data:UserData):void{
        const node = App.Util.find<cc.Node>(`gameLayout/play_0${seat}`,this.node);
        if (App.Util.isValid(data) && App.Util.isValid(node)){
            this._seatInfo.inset(seat,data);
            App.setLableText(node,'head/lblName',data.UserName,'...',5);
            App.setLableText(node,'head/lblCoin',App.Util.formatScore(data.Coin));
            App.Avatar.setHead(data.Avatar,App.Util.find<cc.Sprite>(`head/imgHead`,node,'cc.Sprite'));
            App.Util.find<cc.Node>(`head/imgIdentity`,node).active = false;
            this._setState('',seat);
            this._clearTime(seat);
        }
    }

    private _movePokerActive(from:cc.Vec2,toSeat:number,endCall?:(...args:any)=>void){
        // 播放发牌动画
        const parent = this.moveNode.parent;
        parent.opacity = 0;
        if (this._ghostNode.length < 1){
            // 设置发牌动画属性
            this.moveNode.zIndex = 10;
            const texture = new cc.RenderTexture();
            texture.initWithSize(this.node.width, this.node.height); // 这里传入的必须是屏幕窗口尺寸
            const spriteFrame = new cc.SpriteFrame();
            spriteFrame.setTexture(texture);
            this.moveNode.getChildByName('Camera').getComponent(cc.Camera).targetTexture = texture;
            // 创建跟随精灵
            for (let i = 0; i < 5; ++i){
                let ghost = new cc.Node(`ghost0${i}`);
                ghost.parent = parent;
                ghost.scaleY = -2;
                ghost.scaleX = 2;
                ghost.zIndex = 10 - i;
                ghost.opacity = 100 - i * 15;
                ghost.addComponent(cc.Sprite).spriteFrame = spriteFrame;
                this._ghostNode.push(ghost);
            }
        }
        	
        const _ghostFollow = ()=>{
            this._ghostNode.forEach((ghost, i) => {
                const dis = (ghost.position as any).sub(this.moveNode.position).mag();
                // 给个误差范围，涉及到浮点数，dis的计算不可能精准，小于0.5就可以认为是静止了
                if (dis < 0.5) return; 
                cc.tween(ghost).to(i * 0.04 + 0.04,{x:this.moveNode.x,y:this.moveNode.y}).start();
            });
        };
        const _moveActive = (targetPos:cc.Vec2,data:any,cb:(dt:any)=>void)=>{
            this.moveNode.setPosition(from);
            for (let it of this._ghostNode)it.setPosition(this.moveNode.getPosition());
            cc.tween(this.moveNode).sequence(cc.callFunc(()=>{
                parent.opacity = 255;
                this.moveNode.active = true;
                this.moveNode.opacity = 0;
                this.schedule(_ghostFollow, 0.1, cc.macro.REPEAT_FOREVER);
            }), cc.fadeIn(0.01),cc.delayTime(0.5),cc.moveTo(0.3,targetPos),cc.fadeOut(0.1),cc.callFunc((target,d:any)=>{
                cc.tween(this.moveNode).stop();
                parent.opacity = 0;
                this.unschedule(_ghostFollow);
                cb && cb(d);
            },this,data)).start();
        };
        
        const targetNode:cc.Node = this.moveNode.parent.getChildByName(`poker${toSeat}`);
        _moveActive(targetNode.getPosition(),toSeat,(data:any)=>{
            endCall && endCall(data);
        },);
    }

    private _setSettlement(isShow:boolean,cb?:()=>void){
        if (isShow) {
            this.pnlGameOver.opacity = 0;
            this.pnlGameOver.active = true;
            const size:cc.Size = cc.view.getFrameSize();
            this.pnlGameOver.width = size.width;
            this.pnlGameOver.height = size.height;
        }
        cc.tween(this.pnlGameOver).stop();
        cc.tween(this.pnlGameOver)
        .call(()=>{
            if (isShow){
                const isCan = GameModule.userInfo.Coin >= GameModule.roomData.BetMin;
                App.Util.find<cc.Node>('gameOver/btnsNode/btnContinueGame',this.pnlGameOver).active = isCan;
                const str = App.getText('landlord.auto_leave');
                const lblTips = App.Util.find<cc.RichText>('gameOver/lblTips',this.pnlGameOver,'cc.RichText');
                let time = 15;
                this._autoLeave = setInterval(()=>{
                    lblTips.string = App.Util.format(str,time);
                    --time < 0 && this._setSettlement(false,()=>{GameModule.exitRoom()});
                },1000);
            }
        }).sequence(cc.fadeTo(0.2, isShow ? 255 : 0), cc.callFunc(() => {
            if (this._autoLeave){
                clearInterval(this._autoLeave);
                this._autoLeave = null;
            }
            if (!isShow) {
                this.pnlGameOver.active = false;
                this.pnlGameOver.opacity = 255;
            }
            cb && cb();
        })).start();
    }

    private _clearTime(seat:number){
        if (this._waitHand){
            clearInterval(this._waitHand);
            this._waitHand = undefined;
        }
        const lbl:cc.Label =  this.lblTimes[seat];
        if (App.Util.isInvalid(lbl) || !lbl.node.parent.active) return ;
        lbl.node.parent.active ? cc.tween(lbl.node.parent)
        .to(0.1,{opacity:0},{easing:'quadIn'})
        .call(()=>{
                lbl.string = '';
        }).start() : (lbl.string = '');
    }

    private _setWaitTime(seat:number,dealTime:number){
        this._clearTime(seat);
        this._setState('',seat);
        const lbl:cc.Label =  this.lblTimes[seat];
        if (App.Util.isInvalid(lbl)) return ;

        if (dealTime < 1) return ;
        cc.tween(lbl.node.parent).to(0.1,{opacity:255},{easing:'quadIn'})
        .call(()=>{
            lbl.string = dealTime > 0 ? `${GameModule.MaxWaitTime}`:'';
            let curTime = 0;
            App.Audio.playLoopEffect(`sound/naozhong:game`);
            this._waitHand = setInterval(()=>{
                if (curTime >= dealTime){
                    this._clearTime(seat);
                    App.Audio.stopLoopEffect();
                    if (seat === this._selfSeat){
                        const last = GameModule.getLast(seat,this._discardInfo);
                        const canUnion = GameLogic.findCanDiscard(this._hands,last.seat === seat ? []:last.cards,true);
                        // 自动出牌
                        let can:PokerData[] = canUnion ? canUnion[0].cards.slice(0):[];
                        can.length > 0 && this.handLayout.getComponent(PokerWall).autoSelect(can.slice(0));
                        const pkg:Discard = {
                            cards:can, //打出的牌组信息
                            seat:0,       // 谁出的
                            next:1,       // 下家
                            delayTime:-1,
                        };
                        App.Event.emit(LandlordEvents.EC_DISCARD,pkg);
                        this._canDiscard = null;
                        this.discardCtrlLayout.active = false;
                    }
                } else {
                    lbl.string = `${GameModule.MaxWaitTime-curTime}`;
                    curTime++;
                }          
            },1000);
        }).start();

    }

    private _playEffect(list:PokerData[],seat:number,cb?:()=>void){
        const tmp = GameLogic.getUnion(list);

        if (tmp.type === PokerType.unknow){
            const passSound =['w_pass_yaobuqi','w_pass_buyao','w_pass_guo','w_pass_pass'];
            let idx = App.Util.random(0,3);
            this._setState(this._stateFlag[idx+1],seat);
            GameModule.playEffect(passSound[idx]);
            cb && cb();
            return ;
        }

        let _strSound:string = '';
        let _animation:string = '';
        switch (tmp.type){
            case PokerType.single:_strSound = `w_single_${tmp.cards[0].val}`;break;// 单牌
            case PokerType.pairs:_strSound = `w_pair_${tmp.cards[0].val}`; break;// 对子
            case PokerType.three:_strSound = `w_three_${tmp.cards[0].val}`;break;// 三不带
            case PokerType.bomb:_strSound = 'w_zhadan'; _animation = 'zhadan'; break;// 炸弹
            case PokerType.joker:_strSound = 'w_wangzha'; _animation = 'huojian'; break;// 王炸
            case PokerType.three_single:_strSound = 'w_sandaiyi';break;// 3带1
            case PokerType.three_pairs:_strSound = 'w_sandaidui';break;// 3带2
            case PokerType.four_Single:_strSound = 'w_sidaier';break;// 4带2
            case PokerType.four_pairs:_strSound = 'w_sidailiangdui';break;// 4带2对
            case PokerType.progression:_strSound = 'w_shunzi';break;// 顺子
            case PokerType.progression_pairs:_strSound = 'w_liandui';break;// 顺子
            case PokerType.plane:// 飞机不带
            case PokerType.plane_single:// 飞机带单
            case PokerType.plane_pairs:// 飞机带对子
            _strSound = 'w_feiji';; 
            _animation = 'feiji'; 
            break;
        }

        const effect = this._effects.find(_animation);
        if (App.Util.isValid(effect)){
            !App.Util.isEmpty(_strSound) && GameModule.playEffect(_strSound);
            this._playAnimation(effect,seat,cb);
            return ;
        }

        !App.Util.isEmpty(_strSound) && GameModule.playEffect(_strSound);
        cb && cb();
    }

    private _playAnimation(cfg:EffectCfg, index:number, call?:()=>void) {
        if (App.Util.isInvalid(cfg) || App.Util.isInvalid(cfg.gotoAndPlay[index])){
            console.error(`play DragonBones error.cfg=${cfg && JSON.stringify(cfg)},idx = ${index}`);
            return ;
        }

        console.info(`play DragonBones cfg=${cfg && JSON.stringify(cfg)},idx = ${index}`);
        App.Res.displayDragonBones(this.effectsLayout,`effects/${cfg.path}:room`,cfg.armatureName,cfg.gotoAndPlay[index],cfg.playTimes,call);
    }

    private _clearTable(){
        if (this._autoLeave){
            clearInterval(this._autoLeave);
            this._autoLeave = null;
        }
        [0,1,2].forEach((idx)=>{
            this._clearTime(idx);
            this._setHandsCount(idx,0);
            this._setState('',idx);
            this.imgLandlordFlag[idx].active = false;
            this.showPokes[idx].getComponent(PokerWall).remove();
            this._setHandsCount(idx,0);
            this._setWaitTime(idx,0);
        });
        this.lblNoPoker.node.active = false;
        this.pnlGameOver.active = false;
        this.obviousNode.parent.opacity = 0;
        this.obviousNode.getComponent(PokerWall).remove();
        this.romeInfoNode.active = true;

        this.callLayout.children.forEach((it:cc.Node)=>{it.active = true;});
        this.discardCtrlLayout.children.forEach((it)=>it.active=true);
        this.handLayout.getComponent(PokerWall).remove();
        this.callLayout.active = false;
        this.discardCtrlLayout.active = false;
        this.cannotTips.active = false;
        this._landlord = -1;
        this._discardInfo.clear();
        this._hands = [];
        this._canDiscard = null;
    }

    private _resetSeat(seat:number){
        const node = App.Util.find<cc.Node>(`gameLayout/play_0${seat}`,this.node);
        if (App.Util.isValid(node)){
            App.setLableText(node,'head/lblName','--');
            App.setLableText(node,'head/lblCoin','--');
            App.Avatar.setHead(App.Util.random(0,1),App.Util.find<cc.Sprite>(`head/imgHead`,node,'cc.Sprite'));
            App.Util.find<cc.Node>(`head/imgIdentity`,node).active = false;
        }
    }

    private _setState(str:string,idx:number,col?:cc.Color,delay:number = 1000){
        const lbl:cc.Label = this.lblStates[idx];
        if (App.Util.isInvalid(lbl)) return ;

        this._clearTime(idx);
        if (App.Util.isEmpty(str)){
            lbl.string = '';
            return ;
        }
        delay < 1 && (delay = 1000);
        lbl.node.color = col || cc.color(49,146,113);
        lbl.string = str;
        if (App.Util.isEmpty(str)) return ;

        cc.tween(lbl).stop();
        cc.tween(lbl).sequence(cc.fadeIn(0.5),cc.delayTime(delay),cc.fadeOut(0.5))
        .call(()=>{
            lbl.string = '';
        }).start();
    }

    private _setHandsCount(seat:number,cont:number){
        const lbl = this.lblCounts[seat];
        if (App.Util.isInvalid(lbl)) return ;

        cont < 0 && (cont = 0);
        lbl.string = `${cont}`;
        lbl.node.parent.active = cont > 0;
    }
}
